Documentation Index Fetch the complete documentation index at: https://mintlify.com/Planview/tf_aws_vpc/llms.txt
Use this file to discover all available pages before exploring further.
Overview
NAT (Network Address Translation) gateways enable instances in private subnets to access the internet while preventing inbound connections from the internet. The module supports two NAT gateway deployment modes:
Multiple NAT Gateways - One NAT gateway per availability zone (high availability)
Single NAT Gateway - One shared NAT gateway across all AZs (cost-optimized)
Configuration Variables
Controls whether NAT gateways should be provisioned for private networks. Default: falseDefined in: variables.tf:58-61
Controls whether to provision a single shared NAT gateway across all private networks instead of one per AZ. Default: falseDefined in: variables.tf:63-66
NAT gateways require public subnets to exist, as they must be deployed in public subnets with internet gateway access.
How NAT Gateways Work
Elastic IP Allocation
From main.tf:111-115, Elastic IPs are allocated for NAT gateways:
resource "aws_eip" "nateip" {
count = " ${ var . enable_nat_gateway ? (var . single_nat_gateway ? 1 : length (var . azs )) : 0 } "
vpc = true
}
The count logic:
If enable_nat_gateway = false: 0 EIPs created
If single_nat_gateway = true: 1 EIP created
If single_nat_gateway = false: EIPs created equal to number of AZs
NAT Gateway Creation
From main.tf:117-124, NAT gateways are created in public subnets:
resource "aws_nat_gateway" "natgw" {
count = " ${ var . enable_nat_gateway ? (var . single_nat_gateway ? 1 : length (var . azs )) : 0 } "
allocation_id = " ${ element (aws_eip . nateip .*. id , (var . single_nat_gateway ? 0 : count . index )) } "
subnet_id = " ${ element (aws_subnet . public .*. id , (var . single_nat_gateway ? 0 : count . index )) } "
depends_on = [ "aws_internet_gateway.mod" ]
}
Private Route Configuration
From main.tf:35-41, routes to NAT gateways are added to private route tables:
resource "aws_route" "private_nat_gateway" {
count = " ${ var . enable_nat_gateway ? length (var . azs ) : 0 } "
route_table_id = " ${ element (aws_route_table . private .*. id , count . index ) } "
destination_cidr_block = "0.0.0.0/0"
nat_gateway_id = " ${ element (aws_nat_gateway . natgw .*. id , count . index ) } "
}
Deployment Modes
Multiple NAT Gateways (One Per AZ) This configuration provides high availability by deploying a NAT gateway in each availability zone. module "vpc" {
source = "github.com/terraform-community-modules/tf_aws_vpc"
name = "ha-vpc"
cidr = "10.0.0.0/16"
azs = [
"us-east-1a" ,
"us-east-1b" ,
"us-east-1c"
]
private_subnets = [
"10.0.1.0/24" ,
"10.0.2.0/24" ,
"10.0.3.0/24"
]
public_subnets = [
"10.0.101.0/24" ,
"10.0.102.0/24" ,
"10.0.103.0/24"
]
# Create NAT gateway in each AZ
enable_nat_gateway = true
single_nat_gateway = false
tags = {
Environment = "production"
}
}
Result:
3 NAT gateways created (one per AZ)
3 Elastic IPs allocated
Each private subnet routes through its own AZ’s NAT gateway
High availability: AZ failure doesn’t affect other AZs
Cost: ~0.045 / h o u r p e r N A T g a t e w a y + d a t a p r o c e s s i n g c h a r g e s = 0.045/hour per NAT gateway + data processing charges = ~ 0.045/ h o u r p er N A T g a t e w a y + d a t a p rocess in g c ha r g es = 97.20/month for 3 NAT gatewaysSingle Shared NAT Gateway This configuration reduces costs by using one NAT gateway shared across all availability zones. module "vpc" {
source = "github.com/terraform-community-modules/tf_aws_vpc"
name = "dev-vpc"
cidr = "10.0.0.0/16"
azs = [
"us-west-2a" ,
"us-west-2b" ,
"us-west-2c"
]
private_subnets = [
"10.0.1.0/24" ,
"10.0.2.0/24" ,
"10.0.3.0/24"
]
public_subnets = [
"10.0.101.0/24" ,
"10.0.102.0/24" ,
"10.0.103.0/24"
]
# Create single shared NAT gateway
enable_nat_gateway = true
single_nat_gateway = true
tags = {
Environment = "development"
}
}
Result:
1 NAT gateway created (in first public subnet)
1 Elastic IP allocated
All private subnets route through the same NAT gateway
Lower cost but single point of failure
Cost: ~0.045 / h o u r + d a t a p r o c e s s i n g c h a r g e s = 0.045/hour + data processing charges = ~ 0.045/ h o u r + d a t a p rocess in g c ha r g es = 32.40/monthFully Isolated Private Subnets For workloads that don’t require internet access. module "vpc" {
source = "github.com/terraform-community-modules/tf_aws_vpc"
name = "isolated-vpc"
cidr = "10.0.0.0/16"
azs = [ "eu-west-1a" , "eu-west-1b" ]
private_subnets = [
"10.0.1.0/24" ,
"10.0.2.0/24"
]
# No NAT gateway - fully isolated
enable_nat_gateway = false
# Use VPC endpoints for AWS services
enable_s3_endpoint = true
enable_dynamodb_endpoint = true
tags = {
Environment = "secure"
}
}
Result:
No NAT gateways created
No internet access from private subnets
Use VPC endpoints to access AWS services
Cost: $0 for NAT gateways
Architecture Diagrams
Multiple NAT Gateways Architecture
┌─────────────────────────────────────────────────────────────┐
│ VPC │
│ 10.0.0.0/16 │
│ │
│ ┌───────────────┐ ┌───────────────┐ ┌───────────────┐ │
│ │ us-east-1a │ │ us-east-1b │ │ us-east-1c │ │
│ │ │ │ │ │ │ │
│ │ Public Subnet │ │ Public Subnet │ │ Public Subnet │ │
│ │ 10.0.101.0/24 │ │ 10.0.102.0/24 │ │ 10.0.103.0/24 │ │
│ │ │ │ │ │ │ │ │ │ │
│ │ NAT GW 1 │ │ NAT GW 2 │ │ NAT GW 3 │ │
│ │ │ │ │ │ │ │ │ │ │
│ └──────┼────────┘ └──────┼────────┘ └──────┼────────┘ │
│ │ │ │ │
│ ┌──────▼────────┐ ┌──────▼────────┐ ┌──────▼────────┐ │
│ │ │ │ │ │ │ │
│ │Private Subnet │ │Private Subnet │ │Private Subnet │ │
│ │ 10.0.1.0/24 │ │ 10.0.2.0/24 │ │ 10.0.3.0/24 │ │
│ └───────────────┘ └───────────────┘ └───────────────┘ │
│ │
└─────────────────────────────────────────────────────────────┘
Single NAT Gateway Architecture
┌─────────────────────────────────────────────────────────────┐
│ VPC │
│ 10.0.0.0/16 │
│ │
│ ┌───────────────┐ ┌───────────────┐ ┌───────────────┐ │
│ │ us-east-1a │ │ us-east-1b │ │ us-east-1c │ │
│ │ │ │ │ │ │ │
│ │ Public Subnet │ │ Public Subnet │ │ Public Subnet │ │
│ │ 10.0.101.0/24 │ │ 10.0.102.0/24 │ │ 10.0.103.0/24 │ │
│ │ │ │ │ │ │ │ │
│ │ NAT GW │ │ │ │ │ │
│ │ │ │ │ │ │ │ │
│ └──────┼────────┘ └───────────────┘ └───────────────┘ │
│ │ │ │ │
│ ┌──────▼────────┐ ┌──────▼────────┐ ┌──────▼────────┐ │
│ │ └───────┼──┼───────┘ └──┼───────┘ │ │
│ │Private Subnet │ │Private Subnet │ │Private Subnet │ │
│ │ 10.0.1.0/24 │ │ 10.0.2.0/24 │ │ 10.0.3.0/24 │ │
│ └───────────────┘ └───────────────┘ └───────────────┘ │
│ │
└─────────────────────────────────────────────────────────────┘
Use Cases
Production Environments
module "vpc" {
source = "github.com/terraform-community-modules/tf_aws_vpc"
name = "production-vpc"
cidr = "10.0.0.0/16"
azs = [ "us-east-1a" , "us-east-1b" , "us-east-1c" ]
private_subnets = [ "10.0.1.0/24" , "10.0.2.0/24" , "10.0.3.0/24" ]
public_subnets = [ "10.0.101.0/24" , "10.0.102.0/24" , "10.0.103.0/24" ]
# High availability NAT configuration
enable_nat_gateway = true
single_nat_gateway = false # One NAT gateway per AZ
tags = {
Environment = "production"
Criticality = "high"
}
}
Development/Testing Environments
module "vpc" {
source = "github.com/terraform-community-modules/tf_aws_vpc"
name = "dev-vpc"
cidr = "10.1.0.0/16"
azs = [ "us-west-2a" , "us-west-2b" ]
private_subnets = [ "10.1.1.0/24" , "10.1.2.0/24" ]
public_subnets = [ "10.1.101.0/24" , "10.1.102.0/24" ]
# Cost-optimized NAT configuration
enable_nat_gateway = true
single_nat_gateway = true # Single shared NAT gateway
tags = {
Environment = "development"
Criticality = "low"
}
}
Secure Database Tier
module "vpc" {
source = "github.com/terraform-community-modules/tf_aws_vpc"
name = "secure-database-vpc"
cidr = "10.2.0.0/16"
azs = [ "eu-central-1a" , "eu-central-1b" , "eu-central-1c" ]
database_subnets = [ "10.2.21.0/24" , "10.2.22.0/24" , "10.2.23.0/24" ]
# No NAT gateway - databases are fully isolated
enable_nat_gateway = false
# Use VPC endpoints for AWS service access
enable_s3_endpoint = true
create_database_subnet_group = true
tags = {
Environment = "production"
Tier = "database"
}
}
Cost Considerations
NAT Gateway Pricing (as of 2024):
Hourly charge: ~$0.045 per NAT gateway per hour
Data processing: ~$0.045 per GB processed
Monthly cost per NAT gateway: ~$32.40 (hourly) + data processing
Example Monthly Costs:
Single NAT gateway: ~$32-50/month
Three NAT gateways: ~$97-150/month
Data transfer costs vary by usage
Cost Optimization Strategies
Use Single NAT Gateway for non-production environments
Leverage VPC Endpoints to avoid data processing charges for S3/DynamoDB traffic
Consider NAT Instances for very low-traffic scenarios (not supported by this module)
Monitor Data Transfer to identify optimization opportunities
Best Practices
Production Recommendations:
✓ Use single_nat_gateway = false for high availability
✓ Deploy NAT gateways in all availability zones
✓ Monitor NAT gateway metrics (BytesOutToDestination, BytesInFromSource)
✓ Use VPC endpoints to reduce NAT gateway data processing costs
Common Mistakes:
Enabling NAT gateway without public subnets (deployment fails)
Using single NAT gateway in production (single point of failure)
Not considering data processing costs for high-traffic workloads
Forgetting that database and ElastiCache subnets share private route tables
Troubleshooting
Private Instances Can’t Access Internet
Check:
enable_nat_gateway = true is set
Public subnets exist and have internet gateway routes
Private subnet route tables have routes to NAT gateway (main.tf:35-41)
Security groups allow outbound traffic
Network ACLs allow outbound traffic
High NAT Gateway Costs
Solutions:
Enable S3 VPC endpoint to avoid S3 traffic through NAT gateway
Enable DynamoDB VPC endpoint for DynamoDB traffic
Review CloudWatch metrics to identify high-traffic sources
Consider AWS PrivateLink for other AWS services
Single NAT Gateway Failure
Impact:
All private subnets lose internet access
Cross-AZ data transfer charges for subnets in other AZs
Solution:
# Upgrade to high availability
single_nat_gateway = false
Subnet Types Configure private, public, and database subnets
VPC Endpoints Reduce NAT gateway costs with VPC endpoints